#ifndef UNIT_H_
#define UNIT_H_

#include <sstream>
#include <string>
#include <vector>

using namespace std;

class Unit
{
public:
    int toBaseUnitValue(const int& value_i) const;

    virtual vector<Unit*>& getUnitSeq() = 0;
    
    void eachOutput(ostream& os_io, const int& baseValue_i, void (*print)(ostream&, int&, Unit&, bool&));
    void zeroOutput(ostream& os_io, void (*print)(ostream&, Unit&));
    void baseOutput(ostream& os_io, const int& baseValue_i, void (*print)(ostream&, const int&, Unit&));
    
    int getValue() const;
    string getName() const;

protected:
    Unit(const string& name_i, const int& ratioToBase_i);

private:
    string name_m;
    int ratioToBase_m;
};

typedef vector<Unit*> UnitSeq;
 
class LenUnit: public Unit
{
public:
    LenUnit(const string& name_i, const int& ratioToBase_i);

    static LenUnit& getMile();    
    static LenUnit& getYard();
    static LenUnit& getFeet();
    static LenUnit& getBaseUnit();

public:
    virtual UnitSeq& getUnitSeq();

};

#define MILE (LenUnit::getMile())
#define YARD (LenUnit::getYard())
#define FEET (LenUnit::getFeet())
#define BASELENGTH (LenUnit::getBaseUnit())


class CubUnit: public Unit
{
public:
    CubUnit(const string& name_i, const int& ratioToBase_i);

    static CubUnit& getOZ();
    static CubUnit& getTBSP();
    static CubUnit& getTSP();
    static CubUnit& getBaseUnit();

public:
    virtual UnitSeq& getUnitSeq();
};

#define OZ (CubUnit::getOZ())
#define TBSP (CubUnit::getTBSP())
#define TSP (CubUnit::getTSP())
#define BASECUBAGE (CubUnit::getBaseUnit())


#endif /* UNIT_H_ */

